package com.flaskpy.web.eternity.admin.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/*
*
* ThreadPoolExecutor池子的处理流程如下：　　

1）当池子大小小于corePoolSize就新建线程，并处理请求(不会关闭)

2）当池子大小等于corePoolSize，把请求放入workQueue中，池子里的空闲线程就去从workQueue中取任务并处理

3）当workQueue放不下新入的任务时，新建线程入池，并处理请求，如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

4）另外，当池子的线程数大于corePoolSize的时候，多余的线程会等待keepAliveTime长的时间，如果无请求可处理就自行销毁

其会优先创建  corePoolSize 线程， 当继续增加线程时，先放入Queue中，当 corePoolSize  和 Queue 都满的时候，
* 就增加创建新线程，当线程达到MaxPoolSize的时候，就会抛出错 误 org.springframework.core.task.TaskRejectedException
* */
@Configuration
@EnableAsync
public class AsyncTaskConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);       //初始化核心线程数（最小线程数,不会自动关闭的）
        taskExecutor.setQueueCapacity(50);  //最大队列 (队列超出才会开启新的线程，否则用core线程)
        taskExecutor.setMaxPoolSize(15);        //最大线程（超出异常）

        taskExecutor.setKeepAliveSeconds(30);   //最大空闲时间(秒)
        /**
         * 拒绝策略 默认new ThreadPoolExecutor.AbortPolicy()
         * Reject策略预定义有四种：
         * (1)ThreadPoolExecutor.AbortPolicy策略，是默认的策略,处理程序遭到拒绝将抛出运行时 RejectedExecutionException。
         * (2)ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃.
         * (3)ThreadPoolExecutor.DiscardPolicy策略，不能执行的任务将被丢弃.
         * (4)ThreadPoolExecutor.DiscardOldestPolicy策略，如果执行程序尚未关闭，则位于工作队列头部的任务将被删除，
         * 然后重试执行程序（如果再次失败，则重复此过程）.
         */
//        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setThreadNamePrefix("default-thread-");    //线程前缀
        taskExecutor.setWaitForTasksToCompleteOnShutdown(false);  //shutdown策略，false立即关闭，true等待空成后关闭
        taskExecutor.setAwaitTerminationSeconds(60);
        taskExecutor.initialize();
        return taskExecutor;
    }


}
